package com.google.code.tretris.server;

import java.util.ArrayList;
import java.util.Collection;

import android.util.Log;

import com.google.code.tretris.events.MoveEvent;
import com.google.code.tretris.events.UpdateBoardEvent;
import com.google.code.tretris.network.game.GameActionListener;

public class GamePlay implements GameActionListener {
	private final Collection<GamePlayer> gamePlayers;
	private int playersInPlay;
	private ArrayList<HeartbeatListener> heartbeatListeners = new ArrayList<HeartbeatListener>();

	GamePlay(final Collection<GamePlayer> gamePlayers) {
		if ((gamePlayers == null) || (gamePlayers.size() < 1)) {
			throw new IllegalArgumentException(
					"Can not start game play with null or 0 clients");
		}
		this.gamePlayers = gamePlayers;
		Log.d("GamePlay", "Setting up gameplay with " + gamePlayers.size()
				+ " clients");
		playersInPlay = gamePlayers.size();
	}

	public synchronized void addHeartbeatListener(HeartbeatListener listener) {
		if ((listener != null) && (!heartbeatListeners.contains(listener))) {
			heartbeatListeners.add(listener);
		}
	}

	public synchronized void removeHeartbeatListener(HeartbeatListener listener) {
		if ((listener != null) && (heartbeatListeners.contains(listener))) {
			heartbeatListeners.remove(listener);
		}
	}

	public synchronized void heartbeat() {
//		Log.d("GamePlay", "Heartbeat for " + gamePlayers.size() + " clients");

		ArrayList<UpdateBoardEvent> updateMessages = new ArrayList<UpdateBoardEvent>();
		for (GamePlayer gamePlayer : gamePlayers) {
			if (gamePlayer.isInplay()) {
//				Log.d("GamePlay", "Client " + gamePlayer.getClientID()
//						+ " gets a heartbet");
				gamePlayer.heartbeat();
				if (!gamePlayer.isInplay()) {
					// fire client is out of play.
				} else {
					UpdateBoardEvent event = new UpdateBoardEvent(
							gamePlayer.getClientID(),
							gamePlayer.getActiveTetromino().getX(),
							gamePlayer.getActiveTetromino().getY(),
							gamePlayer.getActiveTetromino().getRotation(),
							gamePlayer.getActiveTetromino().getTetromino().letter,
							gamePlayer.getGameboard().getBlocks());
					updateMessages.add(event);
				}
			} else {
				Log.d("GamePlay", "Client " + gamePlayer.getClientID()
						+ " is out of play");
				decPlayers();
			}
		}
		if (playersInPlay > 0) {
			for (HeartbeatListener listener : heartbeatListeners) {
				listener.heartbeatResult(updateMessages);
			}
		} else {
			for (HeartbeatListener listener : heartbeatListeners) {
				listener.gameOver();
			}
		}
	}

	private synchronized void decPlayers() {
		playersInPlay--;
	}

	public synchronized int getPlayersInPlay() {
		return playersInPlay;
	}

	public void move(MoveEvent moveEvent) {
		for (GamePlayer gamePlayer : gamePlayers) {
			if (gamePlayer.getClientID().equals(moveEvent.getUserId())) {
				Log.d("GamePlay", "Pushing " + moveEvent.toString()
						+ " to client: " + gamePlayer.getClientID());
				gamePlayer.pushEvent(moveEvent);
			}
		}
	}

	public void rotate(MoveEvent moveEvent) {
		for (GamePlayer gamePlayer : gamePlayers) {
			if (gamePlayer.getClientID().equals(moveEvent.getUserId())) {
				Log.d("GamePlay", "Pushing " + moveEvent.toString()
						+ " to client: " + gamePlayer.getClientID());
				gamePlayer.pushEvent(moveEvent);
			}
		}
	}

	public void update(UpdateBoardEvent e) {
		Log.d("GamePlay", "Update callback.");
	}
}
